﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PessModel;
using System.IO;
using System.Data;
using PessMvc.Helpers;
using PessMvc.Models;
using System.Web.Security;
using PessMvc.Lib;
using System.Text;

namespace PessMvc.Controllers
{
    public class ContractController : Controller
    {
        //
        // GET: /Contract/
        PESSEntities db;        
        public ContractController()
        {
            db = new PESSEntities();
        }
        public ActionResult Index()
        {
            return View(db.Contracts);
        }


        public string Upload(HttpPostedFileBase fileData)
        {
            //var fileName = this.Server.MapPath("~/uploads/" + System.IO.Path.GetFileName(file.FileName));
            //file.SaveAs(fileName);

            //int? activityID = db.Archives.Find(archiveID).Subject.ActivityID;

            // Verify that the user selected a file
            if (fileData != null && fileData.ContentLength > 0)
            {
                // extract only the fielname
                var fileName = Path.GetFileName(fileData.FileName);
                // store the file inside ~/App_Data/uploads folder
                var path = Path.Combine(Server.MapPath("~/App_Data/Contracts/"));//, archiveID.ToString());
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                fileData.SaveAs(Path.Combine(path, fileName));

                //Add Contract info to db.
                if (db.Contracts.Where(c => c.Title == fileName).Count() <= 0)
                {
                    FileInfo fileInfo = new FileInfo(Path.Combine(path, fileName));
                    db.Contracts.Add(new Contract { Title = fileName, FilePath = path, TimeStamp = fileInfo.CreationTime, FileSize = (int)(fileInfo.Length / 1024) });
                    db.SaveChanges();
                }
                else
                {//Contract exits. Update procedure
                    Contract contract = db.Contracts.Where(a => a.Title == fileName).SingleOrDefault();
                    FileInfo fileInfo = new FileInfo(Path.Combine(path, fileName));
                    contract.FileSize = (int)(fileInfo.Length / 1024);
                    contract.TimeStamp = fileInfo.CreationTime;
                    db.Entry(contract).State = EntityState.Modified;
                    db.SaveChanges();
                }
            }

            return "ok";
        }

        public ActionResult AssignExperts(int contractID)
        {
            ViewBag.ContractID = contractID;
            //ViewBag.ActivityID = db.ExpertGroups.Find(expertGroupID).ActivityID;
            var allexperts = db.ExpertJudges;
            var choosedExps = from ca in db.Contracts.Find(contractID).ContractAssignments//ExpertJudges.Select(c => c.SerialNumber);
                              join e in db.ExpertJudges on ca.ExpertSN equals e.SerialNumber
                              select e.SerialNumber;
            var available = (from a in allexperts
                             where choosedExps.Contains(a.SerialNumber) == false
                             select a).ToList();

            return View(available.ToExpertJudgeModelList());
        }
        [HttpPost, ActionName("AssignExperts")]
        public ActionResult AssignExpertsConfirmed(int contractID)
        {
            if(Request["ExpertSN"]!=null)
            {
                string[] selectedExpertSNList = Request["ExpertSN"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                Contract contract = db.Contracts.Find(contractID);
                if (contract != null)//verify that contract exists.
                {
                    foreach (string sn in selectedExpertSNList)
                    {
                        if (contract.ContractAssignments.Where(ca => ca.ExpertSN.Trim() == sn.Trim()).Count() == 0)//verify that the contract does not already contain the expert.
                        {
                            ExpertJudge expert = db.ExpertJudges.Find(sn);
                            contract.ContractAssignments.Add(new ContractAssignment() {  ContractID=contractID, ExpertSN=sn});
                            db.SaveChanges();
                        }                    
                    }
                }
            }
            return RedirectToAction("Experts", "Contract", new { ContractID = contractID });
        }

        public ActionResult Experts(int contractID)
        {
            var contract = db.Contracts.Find(contractID);
            ViewBag.ContractTitle = contract.Title;
            var experts = from a in contract.ContractAssignments
                          select new ContractExpertModel(a.ExpertJudge.ToExpertJudgeModel()){ ContractID = contractID, IsContractSigned=a.Signed };
            ViewBag.ContractID = contractID;
            return View(experts);
        }

        public ActionResult DismissExperts(int contractID)
        {
            string[] selectedExpertSNList = Request["ExpertSN"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            Contract contract = db.Contracts.Find(contractID);
            if (contract != null)//verify that contract exists.
            {
                foreach (string sn in selectedExpertSNList)
                {
                    if (contract.ContractAssignments.Where(ca => ca.ExpertSN.Trim() == sn.Trim()).Count() >=1)//verify that the contract contains the expert.
                    {
                        ContractAssignment assignment = db.ContractAssignments.Find(contractID,sn);
                        contract.ContractAssignments.Remove(assignment);
                        db.SaveChanges();
                    }
                }
            }
            return RedirectToAction("Experts", "Contract", new { ContractID = contractID });
        }

        [Authorize(Roles="ExpertJudge")]
        public ActionResult Sign()
        {
            //IExpertJudgeBL  ibl=new ExpertJudgeBL();

            ExpertJudge expert = db.ExpertJudges.Find(Membership.GetUser().UserName);
            if (Roles.IsUserInRole("ExpertJudge") && !Utility.IsContractSigned(expert.SerialNumber))
            {
                ContractAssignment cAssignment = expert.ContractAssignments.Where(c => c.Signed != true).First();
                if (cAssignment != null)
                {
                    return View(cAssignment.Contract);
                }
            }
            return RedirectToAction("Index","Activity");
        }

        [HttpPost]
        public ActionResult Sign(int contractID)
        {
            ContractAssignment assignment = db.ContractAssignments.Find(contractID, Membership.GetUser().UserName);
            if (assignment != null)
            {
                assignment.Signed = true;
                db.Entry(assignment).State = EntityState.Modified;
                db.SaveChanges();
            }
            return RedirectToAction("Index", "Activity");
        }

        public FileStreamResult GetContractPDF(int contractID)
        {
            //1.If there is a pdf file with the same name as archive's SN.
            //2.If there is only one pdf file.
            //3.If there are many pdf files.
            //4.If there is no pdf file.
            string title = "";

            Contract contract = db.Contracts.Find(contractID);
            title = contract.Title;

            FileStream fs;
            if (title != null && title.Length > 0)
            {                
                string fullName = Path.Combine(contract.FilePath, contract.Title);//Title is filename
                //byte[] fileBytes = PessMvc.Helpers.Utility.GetFile(fullName);
                //return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, title);
                fs = new FileStream(fullName, FileMode.Open, FileAccess.Read);
                return File(fs, "application/pdf");
            }
            else
            {
                //byte[] fileBytes = new byte[] { };// PessMvc.Helpers.Utility.GetFile(fullName);
                MemoryStream mStream = new MemoryStream(Encoding.Unicode.GetBytes("中文There is no pdf file to display. Please upload."));
                return File(mStream, "application/text");//"application/pdf");
            }   
        }
        public FileResult Download(int contractID)
        {
            string title = "";
            Contract contract = db.Contracts.Find(contractID);
            title = contract.Title;
            string fullName = Path.Combine(contract.FilePath, contract.Title);//Title is filename
            byte[] fileBytes = PessMvc.Helpers.Utility.GetFile(fullName);
            return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, title);
        }


        [Authorize(Roles = "Admin")]
        public ActionResult Delete(int contractID)
        {
            var contract = db.Contracts.Where(c => c.ID== contractID).FirstOrDefault();
            return View(contract);
        }

        [HttpPost, ActionName("Delete")]
        [Authorize(Roles = "Admin,CountyAdmin")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int contractID)
        {
            Contract contract = db.Contracts.Find(contractID);
            string fullName = Path.Combine(contract.FilePath, contract.Title);//Title is filename
            try
            {
                System.IO.File.Delete(fullName);
            }
            catch { }
            finally
            {
                db.Contracts.Remove(contract);
                db.SaveChanges();
            }
            return RedirectToAction("Index", "Contract");
        }

    }
}
